home *** CD-ROM | disk | FTP | other *** search
- /* << ACE >>
-
- -- Amiga BASIC Compiler --
-
- ** Parser: library and machine code function handling **
- ** Copyright (C) 1998 David Benn
- **
- ** This program is free software; you can redistribute it and/or
- ** modify it under the terms of the GNU General Public License
- ** as published by the Free Software Foundation; either version 2
- ** of the License, or (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- Author: David J Benn
- Date: 26th October-30th November, 1st-13th December 1991,
- 14th,20th-27th January 1992,
- 2nd-17th, 21st-29th February 1992,
- 1st,13th,14th,22nd,23rd March 1992,
- 21st,22nd April 1992,
- 2nd,3rd,11th,15th,16th May 1992,
- 7th,8th,9th,11th,13th,14th,28th,29th,30th June 1992,
- 2nd-8th,14th-19th,26th-29th July 1992,
- 1st-3rd,7th,8th,9th August 1992,
- 6th,7th,22nd December 1992,
- 28th February 1993,
- 12th April 1993,
- 16th,17th December 1993,
- 2nd,3rd,13th January 1994,
- 12th June 1994,
- 5th,20th,28th August 1994,
- 1st,10th September 1994,
- 8th,9th March 1995
- */
-
- #include "acedef.h"
- #include <string.h>
- #include <clib/dos_protos.h>
-
- /* locals */
- static char *reg[] =
- {" ", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
- "a0", "a1", "a2", "a3", "a4", "a5"};
-
- /* externals */
- extern int sym;
- extern int lastsym;
- extern int typ;
- extern int lev;
- extern char id[MAXIDSIZE];
- extern char ut_id[MAXIDSIZE];
- extern char tempshortname[80];
- extern char templongname[80];
- extern char stringval[MAXSTRLEN];
- extern SYM *curr_item;
- extern ACELIBS acelib[NUMACELIBS];
- extern ACELIBS otherlib[NUMLIBS];
- extern char librarybase[MAXIDSIZE + 6];
- extern char libraryname[MAXIDSIZE + 20];
- extern char bmapname[MAXIDSIZE + 20];
- extern BOOL restore_a4;
- extern BOOL restore_a5;
- extern BOOL early_exit;
-
- /* ------------------------- */
- /* Library Function routines */
- /* ------------------------- */
-
- BYTE check_for_ace_lib (char *libname)
- {
- BYTE c = 0;
- /*
- ** If libname is a library used by ACE
- ** open & close it in the normal way.
- */
-
- while (acelib[c].name[0] != '\0' && strcmp (acelib[c].name, "SENTINEL") != 0)
- {
- if (strcmp (acelib[c].name, libname) == 0)
- {
- enter_XREF (acelib[c].base);
- return (c);
- }
- c++;
- }
- return (NEGATIVE);
- }
-
- void enter_new_library (char *libname)
- {
- int cc = 0;
- /*
- ** Enter a library into the list
- ** for future reference by function
- ** declarations which don't specify
- ** the library to be used.
- */
-
- /*
- ** Find libname, first free or maximum entry.
- ** If it's already in the list, libname will
- ** be ignored.
- */
- while (otherlib[cc].name[0] != '\0' &&
- strcmp (otherlib[cc].name, libname) != 0 &&
- strcmp (otherlib[cc].name, "SENTINEL") != 0)
- cc++;
-
- /* maximum? */
- if (strcmp (otherlib[cc].name, "SENTINEL") == 0)
- _error (76); /* can't add another library */
- else if (otherlib[cc].name[0] == '\0')
- {
- /* add a new entry */
- strcpy (otherlib[cc].name, libname);
- make_library_base (libname);
- strcpy (otherlib[cc].base, librarybase);
- }
- }
-
- void make_library_base (char *libname)
- {
- strcpy (librarybase, "_\0");
- strcat (librarybase, libname);
- strcat (librarybase, "Base");
- enter_BSS (librarybase, "ds.l 1");
- }
-
- void make_library_name (char *libname)
- {
- strcpy (libraryname, libname);
- strcat (libraryname, ".library");
- }
-
- void make_bmap_name (char *libname)
- {
- strcpy (bmapname, "ACEbmaps:");
- strcat (bmapname, libname);
- strcat (bmapname, ".bmap");
- }
-
- void get_libname (char *libname, char *ut_libname)
- {
- char *tmp, *ut_tmp;
-
- /* get raw library name (uppercase and untouched) */
- if (sym == ident)
- {
- strcpy (ut_libname, ut_id);
- strcpy (libname, id);
- }
- else
- {
- strcpy (ut_libname, stringval);
- strcpy (libname, strupr (stringval));
- }
-
- /* chop off extension if ".bmap" or ".library" */
- tmp = libname;
- ut_tmp = ut_libname;
- while (*tmp && *tmp != '.')
- {
- tmp++;
- ut_tmp++;
- }
- if (*tmp == '.' &&
- (strcmp (tmp, ".BMAP") == 0 || strcmp (tmp, ".LIBRARY") == 0))
- {
- *tmp = '\0';
- *ut_tmp = '\0';
- }
- }
-
- void library (void)
- {
- char libname[MAXIDSIZE], ut_libname[MAXIDSIZE];
- char lab[80], lablabel[80];
-
- /* open or close a shared library */
-
- insymbol ();
- if (sym == closesym)
- closelibrary ();
- else
- {
- if (sym != ident && sym != stringconst)
- _error (7); /* identifier expected */
- else
- {
- get_libname (libname, ut_libname); /* without extension! */
-
- if (check_for_ace_lib (libname) == NEGATIVE)
- {
- make_library_name (ut_libname); /* exec names are case sensitive */
- make_string_const (libraryname);
- gen ("move.l", "(sp)+", "a1"); /* address of library name in a1 */
- gen ("jsr", "_open_library", " ");
- make_library_base (libname);
- gen ("move.l", "d0", librarybase);
- gen ("cmpi.l", "#0", "d0");
- make_label (lab, lablabel);
- gen ("bne.s", lab, " ");
- gen ("jmp", "_EXIT_PROG", " "); /* quit program if can't open library */
- gen (lablabel, " ", " ");
- enter_XREF ("_open_library");
-
- /* enter new library info' into "other libraries" list */
- enter_new_library (libname);
- }
- }
- insymbol ();
- }
- }
-
- void closelibrary (void)
- {
- char libname[MAXIDSIZE], ut_libname[MAXIDSIZE];
- int cc;
- /* close one or more shared libraries */
-
- insymbol ();
- if (sym != ident && sym != stringconst)
- {
- /*
- ** Close all open shared libraries not
- ** normally closed by ACE at the end of
- ** the program run.
- */
- cc = 0;
- while (otherlib[cc].name[0] != '\0' &&
- strcmp (otherlib[cc].name, "SENTINEL") != 0)
- {
- gen ("move.l", otherlib[cc].base, "a1"); /* library base in a1 */
- gen ("jsr", "_close_library", " ");
- gen ("move.l", "#0", otherlib[cc].base);
- enter_XREF ("_close_library");
- cc++;
- }
- }
- else
- {
- /* close a single shared library */
- get_libname (libname, ut_libname); /* without extension! */
-
- if (check_for_ace_lib (libname) == NEGATIVE)
- {
- make_library_base (libname);
- gen ("move.l", librarybase, "a1"); /* library base in a1 */
- gen ("jsr", "_close_library", " ");
- gen ("move.l", "#0", librarybase);
- enter_XREF ("_close_library");
- }
- insymbol ();
- }
- }
-
- void remove_qualifier (char *funcname)
- {
- /* remove any trailing data type qualifier (%!$) @=& [=! */
- int cc = 0;
-
- /* find end of string */
- while (funcname[cc] != '\0')
- cc++;
- /* is the last character a qualifier? */
- if ((funcname[cc - 1] == '%') || (funcname[cc - 1] == '@') || (funcname[cc - 1] == '#')
- || (funcname[cc - 1] == '[') || (funcname[cc - 1] == '$'))
- funcname[cc - 1] = '\0';
- }
-
-
- BOOL found_func (char *libname, char *ut_funcname, SYM * declared_func)
- {
- /*
- ** Search for function in bmap file and record register usage
- ** and library base offset in symbol table entry for function.
- */
-
- make_bmap_name (libname);
-
- if (search_func (bmapname, ut_funcname, declared_func))
- {
- /* store library name */
- declared_func->libname = (char *) sym_alloc (MAXIDSIZE + 8, MEMF_ANY);
- if (declared_func->libname == NULL)
- {
- puts ("Can't allocate memory for library name in symbol table!");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
- else
- {
- /* found the function */
- strcpy (declared_func->libname, libname);
- return (TRUE);
- }
- }
- else
- /* didn't find the function */
- return (FALSE);
- }
-
- void declare (void)
- {
- /* - declare a library function -- NOT optional.
- - declare an external function -- NOT optional.
- - declare a forward reference to a SUB.
- - declare an instance of a structure.
- */
-
- char funcname[MAXIDSIZE], ut_funcname[MAXIDSIZE];
- char libname[MAXIDSIZE], ut_libname[MAXIDSIZE];
- char extfuncname[MAXIDSIZE + 1];
- int oldlevel, cc;
- int functype = undefined;
- SYM *declared_func;
- BOOL found;
-
- /* all functions and structures must be declared at level ZERO */
-
- oldlevel = lev;
- lev = ZERO;
-
- insymbol ();
-
- if (sym == subsym)
- {
- lev = oldlevel;
- forward_ref ();
- return;
- }
-
- if (sym == structsym)
- {
- lev = oldlevel;
- declare_structure ();
- return;
- }
-
- if (sym != functionsym)
- _error (47);
- else
- {
- insymbol ();
-
- /* type identifiers */
- if (sym == shortintsym || sym == longintsym || sym == addresssym ||
- sym == singlesym || sym == stringsym)
- {
- switch (sym)
- {
- case shortintsym:
- functype = shorttype;
- break;
- case longintsym:
- functype = longtype;
- break;
- case addresssym:
- functype = longtype;
- break;
- case singlesym:
- functype = singletype;
- break;
- case stringsym:
- functype = stringtype;
- break;
- }
- insymbol ();
- }
-
- if (sym != ident)
- _error (7);
- else
- {
- /* get the function's name */
- strcpy (funcname, id);
- strcpy (ut_funcname, ut_id); /* case sensitive version for search! */
- remove_qualifier (funcname);
- remove_qualifier (ut_funcname);
- if (functype == undefined)
- functype = typ;
-
- /* get the LIBRARY symbol and/or parameter list */
- insymbol ();
-
- /* parse parameter list? */
- if (sym == lparen)
- {
- do
- {
- insymbol ();
-
- if (sym == rparen && lastsym == lparen)
- break; /* FuncName() */
-
- /* type indentifier? */
- if (sym == shortintsym || sym == longintsym || sym == addresssym ||
- sym == singlesym || sym == stringsym)
- insymbol ();
-
- /* parameter */
- if (sym != ident)
- _error (7);
- else
- insymbol ();
- }
- while (sym == comma);
-
- if (sym != rparen)
- _error (9);
- else
- insymbol ();
- }
-
- /* EXTERNAL or LIBRARY function? */
- if (sym == externalsym)
- {
- if (ut_funcname[0] != '_')
- {
- strcpy (extfuncname, "_\0");
- strcat (extfuncname, ut_funcname);
- }
- else
- strcpy (extfuncname, ut_funcname);
-
- enter (extfuncname, functype, extfunc, 0);
- enter_XREF (extfuncname);
-
- insymbol ();
- }
- else if (sym != librarysym)
- _error (48);
- else
- {
- enter (funcname, functype, function, 0); /* enter into symbol table */
- declared_func = curr_item;
-
- insymbol ();
-
- if (sym != ident && sym != stringconst)
- {
- /*
- ** Search all bmap files found in acelib and otherlib arrays
- ** for function since no library was specified.
- */
-
- found = FALSE;
-
- /* acelib array */
- cc = 0;
- while (!found && acelib[cc].name[0] != '\0' &&
- strcmp (acelib[cc].name, "SENTINEL") != 0)
- {
- found = found_func (acelib[cc].name, ut_funcname, declared_func);
- cc++;
- }
-
- if (found)
- {
- lev = oldlevel;
- return;
- }
-
- /* otherlib array */
- cc = 0;
- while (!found && otherlib[cc].name[0] != '\0' &&
- strcmp (otherlib[cc].name, "SENTINEL") != 0)
- {
- found = found_func (otherlib[cc].name, ut_funcname, declared_func);
- cc++;
- }
-
- if (!found)
- _error (49);
- }
- else
- {
- /*
- ** Search specified library (bmap file) for the declared function.
- */
- get_libname (libname, ut_libname); /* without extension! */
-
- if (!found_func (libname, ut_funcname, declared_func))
- _error (49);
-
- insymbol ();
- }
- }
- }
- }
- lev = oldlevel;
- }
-
- void load_func_params (SYM * func_item)
- {
- /*
- ** Parse a shared library function's actual parameter-list
- ** and call the function.
- */
- SHORT i, n;
- char ptemp[14][80];
-
- if (sym != lparen)
- {
- _error (14);
- return;
- }
- else
- {
- /* get parameters */
- i = 0;
- do
- {
- insymbol ();
-
- /*
- ** Make ALL parameters longints!
- */
- if (expr () == shorttype)
- make_long ();
-
- /*
- ** Store parameter information temporarily
- ** since expression evaluation may corrupt
- ** data in registers later if loaded now.
- */
- make_temp_long ();
- strcpy (ptemp[i], templongname); /* later -> move.l srctemp,addrbuf */
-
- /* store it */
- gen ("move.l", "(sp)+", templongname);
-
- i++;
- }
- while ((i < func_item->no_of_params) && (sym == comma));
-
- if ((i < func_item->no_of_params) || (sym == comma))
- _error (39); /* parameter count mismatch - too few or too many. */
- else
- {
- /* load parameters into regs */
- for (n = 0; n < func_item->no_of_params; n++)
- {
- /* does reg (a4 or a5 ONLY) need to be preserved? */
- if (func_item->reg[n] == 13) /* a4 */
- {
- restore_a4 = TRUE;
- gen ("move.l", "a4", "_a4_temp");
- enter_BSS ("_a4_temp:", "ds.l 1");
- }
- else if (func_item->reg[n] == 14) /* a5 */
- {
- restore_a5 = TRUE;
- gen ("move.l", "a5", "_a5_temp");
- enter_BSS ("_a5_temp:", "ds.l 1");
- }
-
- /*
- ** Store value in register.
- */
- gen ("move.l", ptemp[n], reg[func_item->reg[n]]);
- }
- }
-
- if (sym != rparen)
- _error (9);
- }
- }
-
- /* ----------------- */
- /* Machine Code CALL */
- /* ----------------- */
-
- void load_mc_params (SYM * sub_ptr)
- {
- SHORT i, n;
- int ptype;
- char p_temp[MAXPARAMS][80];
- int p_type[MAXPARAMS];
-
- /*
- ** Store parameters in stack space of MC subroutine
- ** which is about to be CALLed ala C parameter passing
- ** convention.
- */
-
- i = 0;
- do
- {
- insymbol ();
- ptype = expr ();
-
- /* store parameters temporarily */
- if (ptype == shorttype)
- {
- /* save parameter type */
- p_type[i] = shorttype; /* not DATA type but STORE type (2 or 4 bytes) */
-
- /* create a temporary store */
- make_temp_short ();
- strcpy (p_temp[i], tempshortname); /* later -> move.w srctemp,-(sp) */
-
- /* store it */
- gen ("move.w", "(sp)+", tempshortname);
- }
- else
- /* long,single,string or array */
- {
- /* save parameter type */
- p_type[i] = longtype; /* storage requirement is 4 bytes */
-
- /* create a temporary store */
- make_temp_long ();
- strcpy (p_temp[i], templongname);
-
- /* store it */
- gen ("move.l", "(sp)+", templongname);
- }
-
- i++;
- }
- while ((i < MAXPARAMS) && (sym == comma));
-
- /* push parameters onto stack ala C (see AmigaBASIC manual 6-11) */
- for (n = i - 1; n >= 0; n--)
- {
- if (p_type[n] == shorttype)
- {
- gen ("move.w", p_temp[n], "-(sp)"); /* short */
- sub_ptr->p_type[n] = shorttype;
- }
- else
- {
- gen ("move.l", p_temp[n], "-(sp)"); /* long,string,single,array */
- sub_ptr->p_type[n] = longtype;
- }
- }
-
- sub_ptr->no_of_params = i; /* record number of parameters pushed! */
-
- if (sym != rparen)
- _error (9);
- }
-